/*****************************************************
** Author:
** Date: 2022-01-12
*
*****************************************************/
#include <stdio.h>
#include <string.h>
// #include <sys/time.h>
#include "tm7705.h"


#define log_dbg(_fmt_, ...)   \
            printf("[TM7705][%s:%d][%s][DBG] "_fmt_"\r\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
#define log_inf(_fmt_, ...)   \
            printf("[TM7705][%s:%d][%s][INF] "_fmt_"\r\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
#define log_wrn(_fmt_, ...)   \
            printf("[TM7705][%s:%d][%s][WRN] "_fmt_"\r\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
#define log_err(_fmt_, ...)   \
            printf("[TM7705][%s:%d][%s][ERR] "_fmt_"\r\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)


#define TM7705_DRDY_TIMEOUT     1000    // unit: ms
#define TM7705_DRDY_PERIOD      10      // unit: ms
#define TM7705_DRDY_WAIT_CNT    (TM7705_DRDY_TIMEOUT / TM7705_DRDY_PERIOD)

#define TM7705_REG_COMM     0x00
#define TM7705_REG_SETTING  0x01
#define TM7705_REG_CLOCK    0x02
#define TM7705_REG_DATA     0x03

/* COMMM register */
#define TM7705_COMM_RW_READ  1
#define TM7705_COMM_RW_WRITE 0

#define TM7705_COMM_CH_OFFSET   0
#define TM7705_COMM_STBY_OFFSET 2
#define TM7705_COMM_RW_OFFSET   3
#define TM7705_COMM_RS_OFFSET   4

/* CLOCK register */
enum {
    TM7705_CLOCK_CLK0_FS_20HZ,
    TM7705_CLOCK_CLK0_FS_25HZ,
    TM7705_CLOCK_CLK0_FS_100HZ,
    TM7705_CLOCK_CLK0_FS_200HZ,
};

enum {
    TM7705_CLOCK_CLK1_FS_50HZ,
    TM7705_CLOCK_CLK1_FS_60HZ,
    TM7705_CLOCK_CLK1_FS_250HZ,
    TM7705_CLOCK_CLK1_FS_500HZ,
};

#define TM7705_CLOCK_CLK_0 0 // clk = 2.4576MHz from 2.4576MHz(CLKDIV = 0) or 4.9152MHz(CLKDIV = 1)
#define TM7705_CLOCK_CLK_1 1 // clk = 1MHz from 1MHz(CLKDIV = 0) or 2MHz(CLKDIV = 1)

#define TM7705_CLOCK_CLKDIV_1 0
#define TM7705_CLOCK_CLKDIV_2 1

#define TM7705_CLOCK_CLKDIS_EN  0
#define TM7705_CLOCK_CLKDIS_DIS 1

#define TM7705_CLOCK_FS_OFFSET     0
#define TM7705_CLOCK_CLK_OFFSET    2
#define TM7705_CLOCK_CLKDIV_OFFSET 3
#define TM7705_CLOCK_CLKDIS_OFFSET 4

/**
 * @brief
 * @param  None
 * @retval None
 */
int tm7705_set_clk(tm7705_obj_t *obj)
{
    unsigned char cmd;

    if (obj == NULL) {
        return -1;
    }

    cmd = (TM7705_REG_CLOCK << TM7705_COMM_RS_OFFSET) |
        (TM7705_COMM_RW_WRITE << TM7705_COMM_RW_OFFSET);

    obj->spi_csn_level(0);
    (void)obj->spi_transfer_byte(cmd);

    cmd = (TM7705_CLOCK_CLKDIS_EN << TM7705_CLOCK_CLKDIS_OFFSET) |
        (TM7705_CLOCK_CLKDIV_2 << TM7705_CLOCK_CLKDIV_OFFSET) |
        (TM7705_CLOCK_CLK_0 << TM7705_CLOCK_CLK_OFFSET) |
        (TM7705_CLOCK_CLK0_FS_20HZ << TM7705_CLOCK_FS_OFFSET);

    (void)obj->spi_transfer_byte(cmd);
    obj->spi_csn_level(1);
}

int tm7705_self_cali(tm7705_obj_t *obj)
{
    unsigned char cmd;

    if (obj == NULL) {
        return -1;
    }

    obj->spi_csn_level(0);
    (void)obj->spi_transfer_byte(0x10);
    (void)obj->spi_transfer_byte(0x40);
    obj->spi_csn_level(1);
}

int tm7705_read_drdy(tm7705_obj_t *obj)
{
    unsigned char cmd, val;

    if (obj == NULL) {
        return -1;
    }

    cmd = (TM7705_REG_COMM << TM7705_COMM_RS_OFFSET) |
        (TM7705_COMM_RW_READ << TM7705_COMM_RW_OFFSET);

    obj->spi_csn_level(0);
    (void)obj->spi_transfer_byte(cmd);
    obj->spi_csn_level(1);

    obj->spi_csn_level(0);
    val = obj->spi_transfer_byte(0xff);
    obj->spi_csn_level(1);

    return val >> 7;
}

int tm7705_read_adc(tm7705_obj_t *obj, int ch, unsigned short *data)
{
    int timeout_cnt;
    unsigned char cmd;
    unsigned short val;

    *data = 0;

    if (obj == NULL) {
        return -1;
    }

    /* Waiting for ready */
    timeout_cnt = 0;
    while (obj->drdy_level()) {
        obj->delay_ms(TM7705_DRDY_PERIOD);
        if (++timeout_cnt > TM7705_DRDY_WAIT_CNT) {
            return -2;
        }
    }

    cmd = (TM7705_REG_DATA << TM7705_COMM_RS_OFFSET) |
        (TM7705_COMM_RW_READ << TM7705_COMM_RW_OFFSET) |
        (ch << TM7705_COMM_CH_OFFSET);

    obj->spi_csn_level(0);
    (void)obj->spi_transfer_byte(cmd);
    obj->spi_csn_level(1);

    obj->spi_csn_level(0);
    val = obj->spi_transfer_byte(0xff);
    val <<= 8;
    val += obj->spi_transfer_byte(0xff);
    obj->spi_csn_level(1);

    *data = val;
    return 0;
}

/* End of file */
